home *** CD-ROM | disk | FTP | other *** search
/ PC World Komputer 2001 December / pcwk12201b.iso / Wersje pelne i specjalne / Winamp 2.77 i 3.0beta / wasabi-sdk_beta1.exe / jnetlib / httpserv.cpp < prev    next >
C/C++ Source or Header  |  2001-10-08  |  7KB  |  262 lines

  1. /*
  2.  
  3.   Nullsoft WASABI Source File License
  4.  
  5.   Copyright 1999-2001 Nullsoft, Inc.
  6.  
  7.     This software is provided 'as-is', without any express or implied
  8.     warranty.  In no event will the authors be held liable for any damages
  9.     arising from the use of this software.
  10.  
  11.     Permission is granted to anyone to use this software for any purpose,
  12.     including commercial applications, and to alter it and redistribute it
  13.     freely, subject to the following restrictions:
  14.  
  15.     1. The origin of this software must not be misrepresented; you must not
  16.        claim that you wrote the original software. If you use this software
  17.        in a product, an acknowledgment in the product documentation would be
  18.        appreciated but is not required.
  19.     2. Altered source versions must be plainly marked as such, and must not be
  20.        misrepresented as being the original software.
  21.     3. This notice may not be removed or altered from any source distribution.
  22.  
  23.  
  24.   Brennan Underwood
  25.   brennan@nullsoft.com
  26.  
  27. */
  28.  
  29. /*
  30. ** JNetLib
  31. ** Copyright (C) 2001 Nullsoft, Inc.
  32. ** Author: Justin Frankel
  33. ** File: httpserv.cpp - JNL HTTP GET/POST serving implementation
  34. ** License: see jnetlib.h
  35. **
  36. ** This class just manages the http reply/sending, not where the data 
  37. ** comes from, etc.
  38. */
  39.  
  40. #include "netinc.h"
  41. #include "util.h"
  42.  
  43. #include "httpserv.h"
  44.  
  45. /*
  46.   States for m_state:
  47.     -1 error (connection closed, etc)
  48.     0 not read request yet.
  49.     1 reading headers
  50.     2 headers read, have not sent reply
  51.     3 sent reply
  52.     4 closed
  53. */
  54.  
  55. JNL_HTTPServ::JNL_HTTPServ(JNL_Connection *con)
  56. {
  57.   m_con=con;
  58.   m_state=0;
  59.   m_reply_headers=0;
  60.   m_reply_string=0;
  61.   m_recvheaders=0;
  62.   m_recv_request=0;
  63.   m_recvheaders_size=0;
  64.   m_errstr=0;
  65.   m_reply_ready=0;
  66. }
  67.  
  68. JNL_HTTPServ::~JNL_HTTPServ()
  69. {
  70.   free(m_recv_request);
  71.   free(m_recvheaders);
  72.   free(m_reply_string);
  73.   free(m_reply_headers);
  74.   free(m_errstr);
  75.   delete m_con;
  76. }
  77.  
  78. int JNL_HTTPServ::run()
  79. { // returns: < 0 on error, 0 on connection close, 1 if reading request, 2 if reply not sent, 3 if reply sent, sending data.
  80.   int cnt=0;
  81. run_again:
  82.   m_con->run();
  83.   if (m_con->get_state()==JNL_Connection::STATE_ERROR)
  84.   {
  85.     seterrstr(m_con->get_errstr());
  86.     return -1;
  87.   }
  88.   if (m_con->get_state()==JNL_Connection::STATE_CLOSED) return 4;
  89.  
  90.   if (m_state == 0)
  91.   {
  92.     if (m_con->recv_lines_available()>0)
  93.     {
  94.       char *buf=(char*)malloc(m_con->recv_bytes_available()-1);
  95.       m_con->recv_line(buf,m_con->recv_bytes_available()-1);
  96.       free(m_recv_request);
  97.       m_recv_request=(char*)malloc(strlen(buf)+2);
  98.       strcpy(m_recv_request,buf);
  99.       m_recv_request[strlen(m_recv_request)+1]=0;
  100.       free(buf);
  101.       buf=m_recv_request;
  102.       while (*buf) buf++;
  103.       while (buf >= m_recv_request && *buf != ' ') buf--;
  104.       if (strncmp(buf+1,"HTTP",4) || strncmp(m_recv_request,"GET ",3))
  105.       {
  106.         seterrstr("malformed HTTP request");
  107.         m_state=-1;
  108.       }
  109.       else
  110.       {
  111.         m_state=1;
  112.         cnt=0;
  113.         if (buf >= m_recv_request) buf[0]=buf[1]=0;
  114.  
  115.         buf=strstr(m_recv_request,"?");
  116.         if (buf)
  117.         {
  118.           *buf++=0; // change &'s into 0s now.
  119.           char *t=buf;
  120.           int stat=1;
  121.           while (*t) 
  122.           {
  123.             if (*t == '&' && !stat) { stat=1; *t=0; }
  124.             else stat=0;
  125.             t++;
  126.           }
  127.         }
  128.       }
  129.     }
  130.     else if (!cnt++) goto run_again;
  131.   }
  132.   if (m_state == 1)
  133.   {
  134.     if (!cnt++ && m_con->recv_lines_available()<1) goto run_again;
  135.     while (m_con->recv_lines_available()>0)
  136.     {
  137.       char buf[4096];
  138.       buf[0]=0;
  139.       m_con->recv_line(buf,4096);
  140.       if (!buf[0]) { m_state=2; break; }
  141.       if (!m_recvheaders)
  142.       {
  143.         m_recvheaders_size=strlen(buf)+1;
  144.         m_recvheaders=(char*)malloc(m_recvheaders_size+1);
  145.         if (m_recvheaders)
  146.         {
  147.           strcpy(m_recvheaders,buf);
  148.           m_recvheaders[m_recvheaders_size]=0;
  149.         }
  150.       }
  151.       else
  152.       {
  153.         int oldsize=m_recvheaders_size;
  154.         m_recvheaders_size+=strlen(buf)+1;
  155.         char *n=(char*)malloc(m_recvheaders_size+1);
  156.         if (n)
  157.         {
  158.           memcpy(n,m_recvheaders,oldsize);
  159.           strcpy(n+oldsize,buf);
  160.           n[m_recvheaders_size]=0;
  161.           free(m_recvheaders);
  162.           m_recvheaders=n;
  163.         }
  164.       }
  165.     }
  166.   }
  167.   if (m_state == 2)
  168.   {
  169.     if (m_reply_ready)
  170.     {
  171.       // send reply
  172.       m_con->send_string((char*)(m_reply_string?m_reply_string:"HTTP/1.1 200 OK"));
  173.       m_con->send_string("\r\n");
  174.       if (m_reply_headers) m_con->send_string(m_reply_headers);
  175.       m_con->send_string("\r\n");
  176.       m_state=3;
  177.     }
  178.   }
  179.   if (m_state == 3)
  180.   {
  181.     // nothing.
  182.   }
  183.  
  184.   return m_state;
  185. }
  186.  
  187. char *JNL_HTTPServ::get_request_file()
  188. {
  189.   // file portion of http request
  190.   if (!m_recv_request) return NULL;
  191.   char *t=m_recv_request;
  192.   while (*t != ' ' && *t) t++;
  193.   if (!*t) return NULL;
  194.   while (*t == ' ') t++;
  195.   return t;
  196. }
  197.  
  198. char *JNL_HTTPServ::get_request_parm(char *parmname) // parameter portion (after ?)
  199. {
  200.   char *t=m_recv_request;
  201.   while (*t) t++;
  202.   t++;
  203.   while (*t)
  204.   {
  205.     while (*t == '&') t++;
  206.     if (!strnicmp(t,parmname,strlen(parmname)) && t[strlen(parmname)] == '=')
  207.     {
  208.       return t+strlen(parmname)+1;
  209.     }
  210.     t+=strlen(t)+1;
  211.   }
  212.   return NULL;
  213. }
  214.  
  215. char *JNL_HTTPServ::getheader(char *headername)
  216. {
  217.   char *ret=NULL;
  218.   if (strlen(headername)<1||!m_recvheaders) return NULL;
  219.   char *buf=(char*)malloc(strlen(headername)+2);
  220.   strcpy(buf,headername);
  221.   if (buf[strlen(buf)-1]!=':') strcat(buf,":");
  222.   char *p=m_recvheaders;
  223.   while (*p)
  224.   {
  225.     if (!strnicmp(buf,p,strlen(buf)))
  226.     {
  227.       ret=p+strlen(buf);
  228.       while (*ret == ' ') ret++;
  229.       break;
  230.     }
  231.     p+=strlen(p)+1;
  232.   }
  233.   free(buf);
  234.   return ret;
  235. }
  236.  
  237. void JNL_HTTPServ::set_reply_string(char *reply_string) // should be HTTP/1.1 OK or the like
  238. {
  239.   free(m_reply_string);
  240.   m_reply_string=(char*)malloc(strlen(reply_string)+1);
  241.   strcpy(m_reply_string,reply_string);
  242. }
  243.  
  244. void JNL_HTTPServ::set_reply_header(char *header) // "Connection: close" for example
  245. {
  246.   if (m_reply_headers)
  247.   {
  248.     char *tmp=(char*)malloc(strlen(m_reply_headers)+strlen(header)+3);
  249.     strcpy(tmp,m_reply_headers);
  250.     strcat(tmp,header);
  251.     strcat(tmp,"\r\n");
  252.     free(m_reply_headers);
  253.     m_reply_headers=tmp;
  254.   }
  255.   else
  256.   {
  257.     m_reply_headers=(char*)malloc(strlen(header)+3);
  258.     strcpy(m_reply_headers,header);
  259.     strcat(m_reply_headers,"\r\n");
  260.   }
  261. }
  262.